package com.mobile.collect.camera2;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.util.Log;
import android.view.Surface;

import com.mobile.collect.utils.FileUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * Created by GHC on 2017/6/27.
 * <p>
 * CameraManager类
 * 主要实现：
 * openCamera() 打开摄像头
 * startPreview() 开启预览
 * stopPreview()  结束预览
 * setPreviewTexture()  给Camera设置SurfaceTexture
 * releaseCamera() 释放摄像头
 */

public class SquareCameraManager {
    private Activity mActivity;
    private int mCameraId;
    private Camera mCamera;

    public SquareCameraManager(Activity activity) {
        mActivity = activity;
    }

    // 打开Camera，传入的是前后置摄像头参数
    // Camera.CameraInfo.CAMERA_FACING_BACK = 0：后置摄像头
    // Camera.CameraInfo.CAMERA_FACING_FRONT = 1：前置摄像头
    public boolean openCamera(int cameraId, int PreviewWidth, int PreviewHeight, int picWidth, int picHeight) {
        try {
            mCameraId = cameraId;
            // 打开Camera
            mCamera = Camera.open(mCameraId);

            Camera.Parameters parameters = mCamera.getParameters();
            // 设置原生Camera的预览分辨率，例如 1280*720
//            parameters.setPreviewSize(Constant.SYSTEM_PREVIEW_WIDTH, Constant.SYSTEM_PREVIEW_HEIGHT);
//            parameters.setPreviewSize(PreviewWidth, PreviewHeight);
//            parameters.setPictureSize(picWidth,picHeight);
            // 设置Camera角度，根据当前屏幕的角度设置
            setCameraDisplayOrientation(mActivity, mCameraId, mCamera);
            mCamera.setParameters(parameters);
            Log.i("GHC", "open camera");
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public void parameters(Camera camera) {
        List<Camera.Size> pictureSizes = camera.getParameters().getSupportedPictureSizes();
        List<Camera.Size> previewSizes = camera.getParameters().getSupportedPreviewSizes();
        Camera.Size psize;
        for (int i = 0; i < pictureSizes.size(); i++) {
            psize = pictureSizes.get(i);
            Log.i("pictureSize", psize.width + " x " + psize.height);
        }
        for (int i = 0; i < previewSizes.size(); i++) {
            psize = previewSizes.get(i);
            Log.i("previewSize", psize.width + " x " + psize.height);
        }
    }

    public static void setCameraDisplayOrientation(Activity activity,
                                                   int cameraId, Camera camera) {
        Camera.CameraInfo info =
                new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

    /*
     * 开启预览，是在GLSurfaceView创建成功后调用
     * */
    public void startPreview() {
        if (mCamera != null) {
            mCamera.startPreview();
        }
    }

    /*
     * 屏幕失去焦点后，停止预览，避免资源浪费
     * */
    public void stopPreview() {
        if (mCamera != null) {
            mCamera.stopPreview();
        }
    }

    /*
     * 将SurfaceTexture与Camera绑定
     * 这样Camera的输出数据，就可以显示在SurfaceTexture上面
     * 而STexture是通过GLSurfaceView创建的，这样GLSView就可以操控STexture的数据了
     * 通过对STexture上数据的处理，可以实现滤镜功能，当然也可以实现我们需要的方形预览
     *
     * 此部分可以看 @2.2
     * */
    public void setPreviewTexture(SurfaceTexture surfaceTexture) {
        if (mCamera != null) {
            try {
                mCamera.setPreviewTexture(surfaceTexture);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /*
     * 退出应用时，释放Camera
     * */
    public void releaseCamera() {
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

    public void takePicture(final Context context,final Action1 action1) {
        if (null != mCamera) {
            mCamera.takePicture(new Camera.ShutterCallback() {
                @Override
                public void onShutter() {

                }
            }, new Camera.PictureCallback() {
                @Override
                public void onPictureTaken(byte[] data, Camera camera) {
                    //base data
                }
            }, new Camera.PictureCallback() {
                @Override
                public void onPictureTaken(final byte[] data, Camera camera) {
                    mCamera.stopPreview();
                    Observable.create(new Observable.OnSubscribe<String>() {
                        @Override
                        public void call(Subscriber<? super String> subscriber) {
                            subscriber.onNext(savePhoto(context, data));
                        }
                    }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(action1);
//                    new Thread(
//                            new Runnable() {
//                                @Override
//                                public void run() {
//
//                                }
//                            }
//                    ).start();
                }
            });
        }
    }


    private String savePhoto(Context context, final byte[] data) {
        File mPicturesPath = context.getExternalCacheDir();
        if (!mPicturesPath.exists()) {
            mPicturesPath.mkdirs();
        }
        File file = FileUtil.getTmpPicFile(System.currentTimeMillis() + ".png");
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(data);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return rotateImageView(context, mCameraId, 90, file.getPath());
    }

    private String rotateImageView(Context context, int cameraId, int orientation, String path) {
        Log.d("rotateImageView", "##### save path: " + path);
        Bitmap bitmap = BitmapFactory.decodeFile(path);

        Log.d("rotateImageView", "bitmap.widh: " + bitmap.getWidth());
        Log.d("rotateImageView", "bitmap.height: " + bitmap.getHeight());

        Bitmap resizeBitmap = null;
        switch (cameraId) {
            case Camera.CameraInfo.CAMERA_FACING_BACK:
                Matrix matrix = new Matrix();
                if (orientation == 90) {
                    matrix.postRotate(90);
                }
                Bitmap cropBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getHeight(), bitmap.getHeight());
                resizeBitmap = Bitmap.createBitmap(cropBitmap, 0, 0, cropBitmap.getWidth(), cropBitmap.getHeight(),
                        matrix, true);
                cropBitmap.recycle();
                ;
                break;
            case Camera.CameraInfo.CAMERA_FACING_FRONT:
                Matrix m = new Matrix();
                m.postScale(-1f, 1f);
                resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
                        m, true);
                break;
        }

        File file = new File(path);
        try {
            FileOutputStream fos = new FileOutputStream(file);
            resizeBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
            resizeBitmap.recycle();


        } catch (Exception e) {
            e.printStackTrace();
        }

        return path;

    }
}
